package com.cxyd.modules.wms.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.cxyd.common.page.PageData;
import com.cxyd.common.service.impl.CrudServiceImpl;
import com.cxyd.common.utils.ConvertUtils;
import com.cxyd.common.utils.ProcResult;
import com.cxyd.common.utils.Result;
import com.cxyd.modules.security.user.SecurityUser;
import com.cxyd.modules.sys.dto.SysUserDTO;
import com.cxyd.modules.sys.service.SysUserService;
import com.cxyd.modules.wms.dao.AllotRecordDao;
import com.cxyd.modules.wms.dao.StockDao;
import com.cxyd.modules.wms.dto.AllotRecordDTO;
import com.cxyd.modules.wms.entity.AllotRecordEntity;
import com.cxyd.modules.wms.entity.ContainerEntity;
import com.cxyd.modules.wms.entity.StockEntity;
import com.cxyd.modules.wms.service.AllotRecordService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
public class AllotRecordServiceImpl extends CrudServiceImpl<AllotRecordDao, AllotRecordEntity, AllotRecordDTO> implements AllotRecordService {
    @Resource
    private AllotRecordDao baseDao;
    @Resource
    private StockDao stockDao;
    @Resource
    private SysUserService userService;

    @Override
    public PageData<AllotRecordDTO> page(Map<String, Object> params) {
        //1.查询库存信息
        final IPage<AllotRecordEntity> page = baseDao.selectPage(
                getPage(params, "create_date", false),
                getWrapper(params)
        );
        //2.获取用户列表
        final List<SysUserDTO> userList = userService.getList();
        //3.将creator与updater的username通过id进行绑定
        page.getRecords().forEach(entity -> {
            if (entity.getCreator() != null) {
                entity.setCreatorName(userService.getUsernameById(entity.getCreator(), userList));
            }
            if (entity.getUpdater() != null) {
                entity.setUpdaterName(userService.getUsernameById(entity.getUpdater(), userList));
            }
        });
        return getPageData(page, AllotRecordDTO.class);
    }

    @Override
    public QueryWrapper<AllotRecordEntity> getWrapper(Map<String, Object> params) {
        String allotNo = (String) params.get("allotNo");
        String spuNo = (String) params.get("spuNo");
        String locate = (String) params.get("locate");
//        String status = (String) params.get("status");

        QueryWrapper<AllotRecordEntity> wrapper = new QueryWrapper<>();
//        wrapper.eq(StringUtils.isNotBlank(status), "status", status);
        wrapper.eq(StringUtils.isNotBlank(allotNo), "allot_no", allotNo);
        wrapper.eq(StringUtils.isNotBlank(locate), "locate", locate);
        wrapper.like(StringUtils.isNotBlank(spuNo), "spu_no", spuNo);
        return wrapper;
    }

    @Override
    public int batchSave(List<AllotRecordEntity> entities) {
        if (entities == null || entities.size() == 0) {
            return 0;
        }
        return baseDao.batchSave(entities);
    }

    @Override
    public Result allotRecordImport(MultipartFile file) {
        //1.生成调拨单号,格式为年月日时分秒
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String allotNo = now.format(formatter);
        Long userId = SecurityUser.getUser().getId();
        //2.解析excel文件
        try (InputStream in = file.getInputStream()) {
            List<AllotRecordEntity> insertList = new ArrayList<>();
            //3.将读取到的Excel内容转为List,并进行必要操作
            List<AllotRecordEntity> excelList = EasyExcel.read(in).head(AllotRecordEntity.class).sheet().doReadSync();
            for (AllotRecordEntity entity : excelList) {
//                //3.1.对关键字段进行校验
                if (entity.getSpuNo() == null || StringUtils.isBlank(entity.getSpuNo())) {
                    throw new Exception("料号不能为空");
                }
                if (entity.getLocate() == null || StringUtils.isBlank(entity.getLocate())) {
                    throw new Exception("库别不能为空");
                }
                if (entity.getPlanQty() == null || entity.getPlanQty().compareTo(BigDecimal.ZERO) < 0) {
                    throw new Exception("数量不能小于0");
                }
                //3.2.填充相关信息
                entity.setAllotNo(allotNo);
                entity.setCreator(userId);
                entity.setUpdater(userId);
                insertList.add(entity);
            }
            int count = baseDao.batchSave(insertList);
            return new Result().success("调拨单成功导入[" + count + "]条数据!");
        } catch (Exception ex) {
            return new Result().error(500, ex.toString());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ProcResult procStockAllot(Map<String, Object> map) {
        //1.获取调拨单号
        String allotNo = (String) map.get("allotNo");
        Long userId = SecurityUser.getUser().getId();
        if (StringUtils.isBlank(allotNo)) {
            return new ProcResult().result("404", "調撥單號不能爲空!");
        }
        //2.获取调拨单所有信息
        QueryWrapper<AllotRecordEntity> qwByAllotNo = new QueryWrapper<>();
        qwByAllotNo.lambda().eq(AllotRecordEntity::getAllotNo, allotNo)
                .eq(AllotRecordEntity::getStatus, 0);
        List<AllotRecordEntity> records = baseDao.selectList(qwByAllotNo);
        if (records == null || records.size() == 0) {
            return new ProcResult().result("404", "調撥單[" + allotNo + "]不存在或已轉庫完成!请核查");
        }
        //3.处理调拨单
        for (AllotRecordEntity record : records) {
            //3.1.根据料号+库别按dataCode排序并匹配库存(必须为原料库-2)
            QueryWrapper<StockEntity> qwByStock = new QueryWrapper<>();
            qwByStock.lambda().eq(StockEntity::getSpuNo, record.getSpuNo())
                    .eq(StockEntity::getPositionType, record.getLocate())
                    .eq(StockEntity::getStockType, "2")
                    .eq(StockEntity::getStockSt, 0)
                    .orderByAsc(StockEntity::getStockQty)
                    .orderByAsc(StockEntity::getUnitName);
            List<StockEntity> stockList = stockDao.selectList(qwByStock);
            //3.2.无匹配库存则跳过
            if (stockList == null || stockList.size() == 0) {
                continue;
            }
            //3.3.匹配成功则进行库存分配
            for (StockEntity stock : stockList) {
                //3.3.1.更新库存信息
                stock.setStockType("1");
                stock.setComments("通过调拨单[" + allotNo + "]转库成功!");
                stock.setUpdater(userId);
                stock.setUpdateDate(new Date());
                stockDao.updateById(stock);
                //3.3.2.更新调拨单状态
                record.setActlQty(record.getActlQty().add(stock.getStockQty()));
                //3.3.3.更新调拨单状态为[转库完成]
                record.setStatus(4);
                record.setUpdater(userId);
                record.setUpdateDate(new Date());
                baseDao.updateById(record);
                if (record.getActlQty().compareTo(record.getPlanQty()) >= 0) {
                    break;
                }
            }
        }
        return new ProcResult().result("0", "调拨单[" + allotNo + "]转库成功!");
    }

    @Override
    public List<AllotRecordDTO> getList(Map<String, Object> params) {
        //1.查询库存信息
        List<AllotRecordEntity> entityList = baseDao.selectList(
                getWrapper(params)
        );
        //2.获取用户列表
        final List<SysUserDTO> userList = userService.getList();
        //3.将creator与updater的username通过id进行绑定
        entityList.forEach(entity -> {
            if (entity.getCreator() != null) {
                entity.setCreatorName(userService.getUsernameById(entity.getCreator(), userList));
            }
            if (entity.getUpdater() != null) {
                entity.setUpdaterName(userService.getUsernameById(entity.getUpdater(), userList));
            }
        });
        return ConvertUtils.sourceToTarget(entityList, AllotRecordDTO.class);
    }
}
